package TDADiccionario;

import java.util.Vector;

import TDAColaCP.Entrada;
import TDAColaCP.Entry;
import TDAColaCP.InvalidKeyException;
import TDALista.Lista;
import TDALista.Position;
import TDALista.PositionList;

public class Diccionario<K, V> implements Dictionary<K, V> {
	private Vector<PositionList<Entry<K,V>>> dictionary;
	private int buckets; //Cantidad de cubetas disponibles en el diccionario
	private int size; //Cantidad de cubetas ocupadas en el diccionario
	
	
	public Diccionario(int buckets){
		dictionary = new Vector<PositionList<Entry<K,V>>>(buckets);
		for(int i=0; i<buckets; i++){
			PositionList<Entry<K,V>> list = new Lista<Entry<K,V>>();
			dictionary.add(list);
		}
		this.buckets = buckets;
		size = 0;		
	}

	
	public int size() {
		return size;
	}

	
	public boolean isEmpty() {
		return size()==0;
	}

	
	public V find(K key) throws InvalidKeyException {
		int bucket = Math.abs(key.hashCode() % buckets);
		
		for(Entry<K,V> e : dictionary.get(bucket)){
			if(e.getKey().equals(key))
				return e.getValue();
		}
		return null;
		
	}

	
	public Iterable<V> findAll(K key) throws InvalidKeyException {
		PositionList<V> toReturn = new Lista<V>();
		int bucket = Math.abs(key.hashCode() % buckets);
		
		for(Entry<K,V> e : dictionary.get(bucket)){
			if(e.getKey().equals(key))
				toReturn.addLast(e.getValue());
		}
		return toReturn;
	}

	
	public Entry<K, V> insert(K key, V value) throws InvalidKeyException {
		Entry<K,V> toInsert = new Entrada<K,V>(key,value);
		int bucket = Math.abs(key.hashCode() % buckets);
		dictionary.get(bucket).addLast(toInsert);
		size++;
		
		return toInsert;
	}

	
	public Entry<K, V> remove(Entry<K, V> e) throws InvalidEntryException {
		K key = e.getKey();
		int bucket = Math.abs(key.hashCode() % buckets);
		PositionList<Entry<K,V>> list = dictionary.get(bucket);
		
		for(Position<Entry<K,V>> p : list.positions()){
			if(p.element().getKey().equals(key))
				return list.remove(p);
		}
		
		return null;
			
	}

	
	public Iterable<Entry<K, V>> entries() {
		PositionList<Entry<K,V>> toReturn = new Lista<Entry<K,V>>();
		for(int i=0; i<size; i++){
			for(Entry<K,V> e : dictionary.get(i))
				toReturn.addLast(e);
		}
		return toReturn;
		
	}

}
